package com.mall.shop.config;

import com.alibaba.fastjson2.JSON;
import com.mall.shop.entity.order.Order;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

@EnableRabbit
@Configuration
@RabbitListener(queues = {"hello-world-queue"})
public class RabbitConfig {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    @PostConstruct
    public void initRabbitTemplate() {
        rabbitTemplate.setMessageConverter(messageConverter());
        rabbitTemplate.setConfirmCallback((CorrelationData data, boolean flag, String cause) -> {
            System.out.println("[CorrelationData] 是当前消息的唯一关联数据：" + data + " [flag] 为消息是否接受成功标识：" + flag + " [cause] 为失败原因：" + cause);
        });
        rabbitTemplate.setReturnsCallback((ReturnedMessage message) -> {
            System.out.println("[ReturnsCallback] 回调信息为：" + message);
        });
    }

    // @PostConstruct 的作用是在当前配置类 RabbitConfig 初始化完成后触发initRabbitTemplate方法，有些类似Bean的后置处理器

    @RabbitHandler
    public void listenerMessage(Message message, Order order, Channel channel) throws IOException {
        System.out.println("监听队列hello-world-queue中的消息，消息为：" + new String(message.getBody(), StandardCharsets.UTF_8));
        System.out.println("监听队列hello-world-queue中的消息，消息为：" + JSON.toJSONString(order));
        // 消息的头属性信息
        MessageProperties messageProperties = message.getMessageProperties();
        // 消息的一个自增标识
        long deliveryTag = messageProperties.getDeliveryTag();
        // 确认本消息签收，第二个参数false标识非批量签收模式
        channel.basicAck(deliveryTag,false);
        // 拒绝本次消息签收，第一个false为是否支持批量，第二个false为拒绝签收的消息是否重新入队列，如果为true在重新入队列
        channel.basicNack(deliveryTag,false,false);
        // basicReject 和 basicNack作用一样，只不过不支持批量签收或拒绝
        channel.basicReject(deliveryTag,true);
    }

    @RabbitHandler
    public void listenerMessage(Message message, String body, Channel channel) {
        System.out.println("监听队列hello-world-queue中的消息，消息为：" + new String(message.getBody(), StandardCharsets.UTF_8));
        System.out.println("监听队列hello-world-queue中的消息，消息为：" + JSON.toJSONString(body));
    }
}
